﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class HYDuctConnectAirrTerminal : IExternalCommand
	{
		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			if (commandData == null)
			{
				throw new System.ArgumentNullException("commandData", "is null");
			}
			this.uiApp = commandData.Application;
			this.doc = this.uiApp.ActiveUIDocument.Document;
			this.sel = this.uiApp.ActiveUIDocument.Selection;
			List<ViewType> list = new List<ViewType>();
            list.Add((ViewType)1);
            list.Add((ViewType)2);
            list.Add((ViewType)4);
			if (!YJKRevitTools.ViewCheck(this.uiApp.ActiveUIDocument, list))
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			RevitVersionFuncs.ClearSelection(this.sel);
			if (HYDuctConnectAirrTerminal.hWndRevit == null)
			{
				HYDuctConnectAirrTerminal.hWndRevit = new YJKWindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			}
			ConnectTerminalForm connectTerminalForm = new ConnectTerminalForm();
			connectTerminalForm.Show(HYDuctConnectAirrTerminal.hWndRevit);
			int wMsg = 7;
			HYDuctConnectAirrTerminal.SendMessage(HYDuctConnectAirrTerminal.hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			Result result;
			for (;;)
			{
				Transaction transaction = null;
				try
				{
					transaction = new Transaction(this.doc, "风管连接风口");
					transaction.Start();
					string text = this.DuctConnTerminal(connectTerminalForm);
					connectTerminalForm.BeAutoCancel = false;
					if (!string.IsNullOrEmpty(text))
					{
						YJKMessageBox.Show(text, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
						this.TransactionRollBack(transaction, false);
					}
					else
					{
						this.doc.Regenerate();
						transaction.Commit();
					}
					continue;
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
					this.TransactionRollBack(transaction, true);
					connectTerminalForm.Close();
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
				catch (Exception ex)
				{
					if (!ex.Message.Equals("取消选择风口"))
					{
						YJKMessageBox.Show(ex.Message);
						this.TransactionRollBack(transaction, false);
					}
					else
					{
						this.TransactionRollBack(transaction, true);
					}
					connectTerminalForm.Close();
					result = Autodesk.Revit.UI.Result.Failed;
				}
				break;
			}
			return result;
		}

		private void TransactionRollBack(Transaction ts, bool beRoll = false)
		{
			if (ts != null)
			{
				TransactionStatus status = ts.GetStatus();
                if ((int)status == 1)
				{
					if (beRoll)
					{
						ts.Commit();
						return;
					}
					ts.RollBack();
					return;
				}
                else if ((int)status == 5)
				{
					ts.RollBack();
				}
			}
		}

		private string DuctConnTerminal(ConnectTerminalForm connTerminal)
		{
			string text = "";
			Duct duct = null;
			List<FamilyInstance> list = null;
			int connType = -1;
			text = this.SelectJudgeDuctAndTerminal(connTerminal, ref duct, ref list, ref connType);
			if (text == "auto")
			{
				return "";
			}
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			HYDuctConnect hyductConnect = new HYDuctConnect();
			switch (connTerminal.TerminalConn)
			{
			case ConnectTerminalForm.ConnStyle.Elbow:
			{
				FormConnAlign formConnAlign = new FormConnAlign();
				if (formConnAlign.ShowDialog() == DialogResult.OK)
				{
					bool beSuccess = hyductConnect.DuctConnectTerminalByElbow(duct, list[0], ref text, formConnAlign.AlignType);
					text = this.GetConnMessage(beSuccess, text);
				}
				break;
			}
			case ConnectTerminalForm.ConnStyle.TakeOff:
			{
				FormConnAlign formConnAlign = new FormConnAlign();
				if (formConnAlign.ShowDialog() == DialogResult.OK)
				{
					bool beSuccess = hyductConnect.DuctConnectAirTerminalTakeOff(duct, list[0], ref text, formConnAlign.AlignType);
					text = this.GetConnMessage(beSuccess, text);
				}
				break;
			}
			case ConnectTerminalForm.ConnStyle.Tee:
			{
				FormConnAlign formConnAlign = new FormConnAlign();
				if (formConnAlign.ShowDialog() == DialogResult.OK)
				{
					bool beSuccess = hyductConnect.ConnectAirTerminalByTee(duct, list[0], ref text, formConnAlign.AlignType);
					text = this.GetConnMessage(beSuccess, text);
				}
				break;
			}
			case ConnectTerminalForm.ConnStyle.Cross:
			{
				FormConnAlign formConnAlign = new FormConnAlign();
				if (formConnAlign.ShowDialog() == DialogResult.OK)
				{
					bool beSuccess = hyductConnect.DuctConnectAirTerminalCross(duct, list[0], list[1], ref text, formConnAlign.AlignType);
					text = this.GetConnMessage(beSuccess, text);
				}
				break;
			}
			case ConnectTerminalForm.ConnStyle.OnDuct:
				hyductConnect.MoveTerminal(duct, list[0], connType);
				hyductConnect.DuctConnSideTerminalTakeOff(duct, list[0], ref text, connType, false);
				break;
			}
			return text;
		}

		private string GetConnMessage(bool beSuccess, string connMSG)
		{
			string result;
			if (!beSuccess)
			{
				if (string.IsNullOrEmpty(connMSG))
				{
					result = "连接失败！";
				}
				else
				{
					result = connMSG;
				}
			}
			else
			{
				result = "";
			}
			return result;
		}

		private string SelectJudgeDuctAndTerminal(ConnectTerminalForm connTerminal, ref Duct duct, ref List<FamilyInstance> terminalList, ref int connType)
		{
			string text = "";
			terminalList = new List<FamilyInstance>();
			try
			{
				ConnectTerminalForm.ConnStyle terminalConn = connTerminal.TerminalConn;
				if (terminalConn > ConnectTerminalForm.ConnStyle.Cross)
				{
					if (terminalConn == ConnectTerminalForm.ConnStyle.OnDuct)
					{
						Reference reference = this.sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new NRDuctFilter(), "请选择贴管连接的水平主风管……");
						duct = (this.doc.GetElementByRef(reference) as Duct);
						reference = this.sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new DuctTerminalFilter(), "选择一个风口……");
						FamilyInstance item = this.doc.GetElementByRef(reference) as FamilyInstance;
						terminalList.Add(item);
						connType = -1;
						text = new HYDuctConnect().CheckTerminalBeCovered(duct, terminalList[0], ref connType);
					}
				}
				else
				{
					Reference reference = this.sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new DuctFilter(), "请选择风口连接用的主风管……");
					duct = (this.doc.GetElementByRef(reference) as Duct);
					reference = this.sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new DuctTerminalHorizontalSelectionFilter(), "选择一个风口……");
					FamilyInstance item = this.doc.GetElementByRef(reference) as FamilyInstance;
					terminalList.Add(item);
					ConnectHelper connectHelper = new ConnectHelper();
					Connector conn = connectHelper.GetDuctConnector(duct)[0];
					int position = ConnectHelper.CheckPositionBetweenElement(connectHelper.GetYJKElementConnector(terminalList[0]), conn);
					text = this.GetJudgeInformation(position);
					if (connTerminal.TerminalConn == ConnectTerminalForm.ConnStyle.Cross && string.IsNullOrEmpty(text))
					{
						reference = this.sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new DuctTerminalSelectionFilter(), "选择另一个风口……");
						FamilyInstance item2 = duct.Document.GetElement(reference) as FamilyInstance;
						terminalList.Add(item2);
						if (terminalList[0].Id.Equals(terminalList[1].Id))
						{
							text = "同一个风口不能构成四通连接！";
						}
						else if (this.CheckDuctTerminal(duct, terminalList[0], terminalList[1], ref text))
						{
							int position2 = ConnectHelper.CheckPositionBetweenElement(connectHelper.GetYJKElementConnector(terminalList[1]), conn);
							text = this.GetJudgeInformation(position2);
						}
					}
				}
			}
            catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
			{
				if (connTerminal.BeAutoCancel)
				{
					return "auto";
				}
				throw ex;
			}
			catch (Exception ex2)
			{
				return ex2.Message;
			}
			return text;
		}

		private string GetJudgeInformation(int position)
		{
			string result = "";
			switch (position)
			{
			case 1:
				result = "不能完成连接，可能原因是，风口应该处于风管的下方。";
				break;
			case 2:
				result = "不能完成连接，可能原因是，风口应该处于风管的上方。";
				break;
			case 3:
				result = "不能完成连接，可能原因是，风口和风管上下位置不正确。";
				break;
			}
			return result;
		}

		private bool CheckDuctTerminal(Duct duct, FamilyInstance fi, FamilyInstance fi2, ref string connMsg)
		{
			bool result = true;
			string name = fi.Symbol.Family.Name;
			string name2 = fi2.Symbol.Family.Name;
			if (name == "侧风口" && name2 == "侧风口")
			{
				double num = duct.GetParameter("偏移量").AsDouble();
				if (fi.GetParameter("偏移量").AsDouble() == num && fi2.GetParameter("偏移量").AsDouble() == num)
				{
					result = true;
				}
				else
				{
					connMsg = "所选侧风口偏移量与主管道偏移量不一致，\n无法使用四通连接。";
					result = false;
				}
			}
			else if (name == "侧风口" || name2 == "侧风口")
			{
				connMsg = "选中的风口一个是侧风口，一个非侧风口，无法连接。";
				result = false;
			}
			return result;
		}

		private UIApplication uiApp;

		private Document doc;

		private Selection sel;

		public static YJKWindowHandle hWndRevit;
	}
}
